/**
*	@file QueryTree.cpp
*
*	@brief this header defines class for query tree
*
*	@author li yuchen
*
*	@date 1/28/2011
*/
#include "QueryTree.h"
using namespace std;

vector<QueryTNode*> QueryTree::vp_query_tnodes_;
vector<vector<QueryTNode*> > QueryTree::query_matrix_;
vector<QueryVarIdx> QueryTree::result_tuple_;
vector<bool>        QueryTree::query_var_type_;
int QueryTree::size_ = 0;

static string ToStringHelper(int left_index,int right_index);
static void DeletePattern(TNode* pattern);

QueryTNode* QueryTree::AddQueryTNode(QueryType q_type, QueryArgumentValue argument_a, QueryArgumentValue argument_b)
{
	QueryTNode* new_query_tnode = new QueryTNode;

	new_query_tnode->q_type = q_type;
	new_query_tnode->argument_a = argument_a;
	new_query_tnode->argument_b = argument_b;
	new_query_tnode->pattern = NULL;
	new_query_tnode->priority = 0;

	vp_query_tnodes_.push_back(new_query_tnode);

	return new_query_tnode;
}

void QueryTree::SetPattern(QueryTNode* query, TNode* pattern, bool isRelaxed)
{
	query->pattern = pattern;
	query->isRelaxed = isRelaxed;
}

string QueryTree::ToString()
{
	string ss_output("QueryTree :\n");
	
	vector<QueryTNode*>::iterator temp_iter;
	for( temp_iter = vp_query_tnodes_.begin();
		temp_iter != vp_query_tnodes_.end();
		temp_iter++)
	{
		stringstream ss_result;
		ss_result << QueryTypeToString((*temp_iter)->q_type) << ":" << endl;
		ss_result << ToStringHelper((*temp_iter)->argument_a,(*temp_iter)->argument_b);
		ss_result << " special type(" << TNodeTypeToString((*temp_iter)->special_type) << ")" << endl << endl;
		ss_output.append(ss_result.str());
	}
	return ss_output;
}

string ToStringHelper(int left_index, int right_index){
	stringstream ss;
	if(left_index == 0)
		ss << "anything : ";
	else if(left_index < 0)
		ss << left_index << " : ";
	else
		ss << left_index << "(" << TNodeTypeToString(QueryVarTable::GetQueryVarType(left_index)) << ")" << " : ";
	if(right_index == 0)
		ss << "anything";
	else if(right_index < 0) 
		ss << right_index;
	else
		ss << right_index << "(" << TNodeTypeToString(QueryVarTable::GetQueryVarType(right_index)) << ")";
	return ss.str();
}

string QueryTree::MatrixToString(){
	
	string ss_output("QueryTree Clustered:\n");

	stringstream ss_result;
	for(int i = 0; i < QueryTree::query_matrix_.size(); i++){
		ss_result << "Cluster " << i << ":" << endl;
		for(int j = 0; j < QueryTree::query_matrix_[i].size(); j++){
			ss_result << QueryTypeToString(QueryTree::query_matrix_[i][j]->q_type) << ": ";
			ss_result << ToStringHelper(QueryTree::query_matrix_[i][j]->argument_a,QueryTree::query_matrix_[i][j]->argument_b) << "  ";
		}
		ss_result << endl << endl;
	}
	ss_output.append(ss_result.str());
	return ss_output;
}

void QueryTree::ClearQueryTree()
{
	vector<QueryTNode*>::iterator temp_iter;
	for( temp_iter = vp_query_tnodes_.begin();
		temp_iter != vp_query_tnodes_.end();
		temp_iter++){
		DeletePattern((*temp_iter)->pattern);
		delete *temp_iter;
	}
	vp_query_tnodes_.clear();
	result_tuple_.clear();
	query_var_type_.clear();
	for(int i = 0; i < query_matrix_.size(); i++){
		query_matrix_[i].clear();
	}
	query_matrix_.clear();
	size_ = 0;
}

void DeletePattern(TNode* pattern){
	if(pattern == NULL) return;
	if(pattern->left_sibling == NULL) return;
	DeletePattern(pattern->left_sibling);
	DeletePattern(pattern->left_sibling->right_sibling);
}